package com.example.hanjyLearn.core;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 好用的json声明工具类，可以像前端那样使用类似于json格式的方式声明变量了
 * @author luchuan
 */
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class MyJson extends LinkedHashMap<String, Object> {

    public static MyJson of(String key, Object value) {
        return MyJson.of(new Object[]{key, value});
    }

    @SuppressWarnings("unchecked")
    public static MyJson of(Object... params) {
        // 兼容单个Map类型的参数
        if (params.length == 1 && params[0] instanceof Map) {
            return MyJson.of((Map<?, ?>) params[0]);
        }
        Assert.isTrue(params.length % 2 == 0, "参数个数必须为偶数");
        return extend(new MyJson(), params);
    }

    public static MyJson of(Map<String, Object> map) {
        MyJson myJson = new MyJson();
        return myJson.extend(map);
    }

    private static MyJson extend(MyJson myJson, Object... params) {
        Assert.isTrue(params.length % 2 == 0, "参数个数必须为偶数");
        if (params.length > 0) {
            for (int pairIndex = 0; pairIndex < params.length; pairIndex += 2) {
                String key;
                Object keyObject = params[pairIndex];
                if (keyObject.getClass().isPrimitive() || keyObject instanceof CharSequence) {
                    key = params[pairIndex].toString();
                } else {
                    throw new BizException("key不能为{}类型", keyObject.getClass().getName());
                }
                Object value = params[pairIndex + 1];
                myJson.put(key, value);
            }
        }
        return myJson;
    }

    /**
     * 扩展，K、V。。。
     * @param params
     * @return
     */
    public MyJson extend(Object... params) {
        return extend(this, params);
    }

    public MyJson extend(Map<String, Object> map) {
        this.putAll(map);
        return this;
    }


//    @SuppressWarnings("unchecked")
//    public <T> T get(String key, TypeReference<T> type) {
//        return (T) get(key);
//    }

    public String getNullableString(String key) {
        return Objects.toString(this.get(key), null);
    }

    public String getNullableString(String key, String defaultValue) {
        return Objects.toString(this.get(key), defaultValue);
    }

    public String getString(String key) throws IllegalArgumentException {
        String value = this.getNullableString(key);
        if (StringUtils.isBlank(value)) {
            throw new BizException("参数无效:{}", key);
        }
        return value;
    }

    public Integer getNullableInt(String key) {
        if (this.get(key) == null) {
            return null;
        }
        return getInt(key);
    }

    public int getInt(String key) throws IllegalArgumentException {
        try {
            return Integer.parseInt(this.getNullableString(key));
        } catch (NumberFormatException e) {
            throw new BizException("参数{}无效！", key);
        }
    }

    public long getLong(String key) throws IllegalArgumentException {
        try {
            return Long.parseLong(this.getNullableString(key));
        } catch (NumberFormatException e) {
            throw new BizException("参数{}无效！", key);
        }
    }

    public Long getNullableLong(String key) {
        if (StringUtils.isBlank(this.getNullableString(key))) {
            return null;
        }
        return getLong(key);
    }
//
//    @JsonIgnore
//    public String toJSONString() {
//        return JacksonUtils.toJson(this);
//    }
//
//    @Override
//    public String toString() {
//        return this.toJSONString();
//    }

    @JsonIgnore
    public String toSuperString() {
        return super.toString();
    }

    @JsonIgnore
    public String toMapString() {
        return super.toString();
    }

    @JsonIgnore
    public String toPrettyMapString() {
        Iterator<Map.Entry<String, Object>> i = entrySet().iterator();
        if (! i.hasNext())
            return "{}";

        StringBuilder sb = new StringBuilder();
        sb.append("{\n");
        for (;;) {
            Map.Entry<String, Object> e = i.next();
            String key = e.getKey();
            Object value = e.getValue();
            sb.append(key);
            sb.append(" = ");
            sb.append(value == this ? "(this Map)" : value);
            if (!i.hasNext())
                return sb.append("\n}").toString();
            sb.append(',').append('\n');
        }
    }

    /**
     * 转换为Map&lt;String, String&gt;格式
     * @return
     */
    public Map<String, String> toMapStringString() {
        return this.entrySet().stream().collect(Collectors.toMap(
            Map.Entry::getKey,
            e -> StringUtils.trimToNull(e.getValue()),
            (v1, v2) -> v2,
            LinkedHashMap::new
        ));
    }

    /**
     * 转换为Map&lt;String, Long&gt;格式
     * @return
     */
    public Map<String, Long> toMapStringLong() {
        return this.entrySet().stream().collect(Collectors.toMap(
            Map.Entry::getKey,
            e -> Long.parseLong(e.getValue().toString()),
            (v1, v2) -> v2,
            LinkedHashMap::new
        ));
    }

    /**
     * 转换为Map&lt;String, Integer&gt;格式
     * @return
     */
    public Map<String, Integer> toMapStringInteger() {
        return this.entrySet().stream().collect(Collectors.toMap(
            Map.Entry::getKey,
            e -> Integer.parseInt(e.getValue().toString()),
            (v1, v2) -> v2,
            LinkedHashMap::new
        ));
    }

}
